package org.jeecg.modules.device.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.device.entity.DeviceInstance;
import org.jeecg.modules.device.entity.DeviceLabel;
import org.jeecg.modules.device.entity.DeviceLabelViewData;
import org.jeecg.modules.device.mapper.DeviceInstanceMapper;
import org.jeecg.modules.device.mapper.DeviceLabelMapper;
import org.jeecg.modules.device.mapper.DeviceLabelViewDataMapper;
import org.jeecg.modules.device.service.IDeviceLabelService;
import org.jeecg.modules.device.service.labelSourceHandle.LabelSourceDataHandle;
import org.jeecg.modules.device.vo.label.DeviceLabelVo;
import org.jeecg.modules.device.vo.label.ViewDataVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备标签服务impl
 *
 * @author zhouwenrong
 * @Description: 设备标签
 * @Version: V1.0
 * @date 2022/01/06
 */
@Slf4j
@Service
public class DeviceLabelServiceImpl extends ServiceImpl<DeviceLabelMapper, DeviceLabel> implements IDeviceLabelService {
    /**
     * 标签映射器
     */
    @Autowired
    private DeviceLabelMapper labelMapper;
    /**
     * 视图数据映射器
     */
    @Autowired
    private DeviceLabelViewDataMapper viewDataMapper;
    /**
     * 实例映射器
     */
    @Autowired
    private DeviceInstanceMapper instanceMapper;

    /**
     * 通过代码
     *
     * @param code 代码
     * @return {@link DeviceLabel}
     */
    @Override
    public DeviceLabel getByCode(String code) {

        final List<DeviceLabel> dataList = this.lambdaQuery().eq(DeviceLabel::getCode, code).list();
        if (dataList.size() > 1) {
            throw new RuntimeException("数据标签的code：" + code + "不唯一，请检查配置！");
        } else if (dataList.size() < 1) {
            throw new RuntimeException("数据标签的code：" + code + "找不到，请检查配置！");
        }
        return dataList.get(0);
    }


    /**
     * 选择通过主id
     *
     * @param mainId 主要id
     * @return {@link List}<{@link DeviceLabel}>
     */
    @Override
    public List<DeviceLabel> selectByMainId(String mainId) {
        return labelMapper.selectByMainId(mainId);
    }

    /**
     * 通过模型id列表
     *
     * @param modelId 模型id
     * @return {@link List}<{@link DeviceLabel}>
     */
    @Override
    public List<DeviceLabel> listByModelId(String modelId) {
        return labelMapper.selectByMainId(modelId);
    }

    /**
     * 通过实例id列表
     *
     * @param instanceId 实例id
     * @return {@link List}<{@link DeviceLabel}>
     */
    @Override
    public List<DeviceLabel> listByInstanceId(String instanceId) {
        return labelMapper.selectByInstanceId(instanceId);
    }

    /**
     * 标签配置
     *
     * @param modelId        模型id
     * @param instanceId     实例id
     * @param defaultTrigger
     * @return {@link List}<{@link DeviceLabel}>
     */
    @Override
    public List<DeviceLabel> labelConfig(String modelId, String instanceId, String defaultTrigger) {
        if (StringUtils.isBlank(modelId)) {
            final DeviceInstance instance = instanceMapper.selectById(instanceId);
            if (instance == null) {
                throw new RuntimeException("设备实例找不到！");
            }
            modelId = instance.getModelBy();
        }
        String finalModelId = modelId;
        return this.lambdaQuery()
                .eq(DeviceLabel::getDeviceModelBy, modelId)
                .eq(DeviceLabel::getEnable, true)
                .eq(StringUtils.isNotBlank(defaultTrigger), DeviceLabel::getDefaultTrigger, defaultTrigger)
                .list()
                .stream()
                .map(label -> {
                    final List<DeviceLabelViewData> viewData = viewDataMapper.selectByLabelId(label.getId());
                    return new DeviceLabelVo(label, viewData);
                })
                .peek(labelVo -> {
                    log.info(labelVo.getViewData().toString());
                    final List<ViewDataVo> viewDatas = labelVo.getViewData().stream().map(viewDataVo -> {
                        log.info("{} - {}", finalModelId, viewDataVo.getKey());
                        Object value = LabelSourceDataHandle.getValue(finalModelId, instanceId, viewDataVo);
                        viewDataVo.length(value + "");
                        return viewDataVo;
                    }).collect(Collectors.toList());
                    labelVo.setViewData(viewDatas);
                    labelVo.setInstanceId(instanceId);
                }).collect(Collectors.toList());

    }

    /**
     * 批量插入视图数据
     *
     * @param labelId     标签id
     * @param viewDataVos 视图数据。沃斯
     */
    @Transactional
    public void batchInsertViewData(String labelId, List<ViewDataVo> viewDataVos) {
        viewDataVos.forEach(viewDataVo -> {
            // 强转成父类
            DeviceLabelViewData viewData = viewDataVo;
            //外键设置
            viewData.setDeviceLabelBy(labelId);
            viewData.setCode(viewDataVo.getKey());
            if (viewDataVo.getConvert() != null) {
                viewData.setDictTable(viewDataVo.getConvert().getDictTable());
                viewData.setDictKey(viewDataVo.getConvert().getDictKey());
                viewData.setDictValue(viewDataVo.getConvert().getDictValue());
            }
            viewDataMapper.insert(viewData);
        });
    }

    /**
     * 救主
     *
     * @param labelVo 标签签证官
     */
    @Override
    @Transactional
    public void saveMain(DeviceLabelVo labelVo) {
        labelVo.setId(labelVo.getCode());
        labelMapper.insert(labelVo);
        batchInsertViewData(labelVo.getId(), labelVo.getViewData());
    }

    /**
     * 更新主要
     *
     * @param labelVo 标签签证官
     */
    @Override
    @Transactional
    public void updateByMain(DeviceLabelVo labelVo) {
        labelMapper.updateById(labelVo);
        // 删除所有显示数据
        viewDataMapper.deleteByLabelId(labelVo.getId());
        // 添加
        batchInsertViewData(labelVo.getId(), labelVo.getViewData());

    }

    /**
     * 通过id获取主要
     *
     * @param id id
     * @return {@link DeviceLabelVo}
     */
    @Override
    public DeviceLabelVo getMainById(String id) {
        final DeviceLabel label = labelMapper.selectById(id);
        final List<DeviceLabelViewData> viewData = viewDataMapper.selectByLabelId(id);

        return new DeviceLabelVo(label, viewData);
    }
}